<?php
/**
 * User: 784855684@qq.com
 * Date: 30/12/2017
 * Time: 17:11
 */
declare(strict_types=1);


namespace AppBundle\Controller;

use AppBundle\Entity\Material;
use AppBundle\Entity\Product;
use AppBundle\Repository\MaterialRepository;
use AppBundle\Repository\ProductRepository;
use AppBundle\Throwable\MaterialEmptyException;
use AppBundle\Utils\MaterialUtil;
use AppBundle\Utils\ProductUtil;
use Doctrine\DBAL\ConnectionException;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\OptimisticLockException;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;

class ProductController extends DefaultController
{
    /**
     * @Route("/product/overview")
     * @return Response
     */
    public function overviewAction()
    {
        return $this->render('product/overview.html.twig');
    }

    /**
     * page of product designing
     * @Route("/product/design")
     * @return Response
     */
    public function designAction()
    {
        return $this->render('product/design.html.twig');
    }

    /**
     * @Route("/product/list")
     * @return JsonResponse
     */
    public function listAction()
    {
        /** @var ProductRepository $respo */
        $respo = $this->getEntityManager()->getRepository(Product::class);
        /** @var Product[] $objects */
        $objects = $respo->findAllAvailable();
        $list = [];
        foreach ($objects as $object) {
            $data = $this->fetchInfo($object);
            $materials = $object->getMaterials();
            $mstr = '';
            foreach ($materials as $material) {
                $mstr .= $material->getName() . ',';
            }

            $data['materials'] = rtrim($mstr, ',');
            $list[] = $data;
        }
        return $this->responseSuccess('', $list);
    }

    /**
     * fetch infomation from material entity
     * @param Product $object
     * @param bool $full
     * @return array
     */
    private function fetchInfo(Product $object, bool $full = false)
    {
        $desc = $object->getDescription();
        if (!$full and mb_strlen($desc) > 20) {
            $desc = mb_substr($desc, 0, 20) . '...';
        }
        return [
            'id' => $object->getId(),
            'name' => $object->getName(),
            'description' => $desc,
            'price' => $object->getPrice(),
            'customer_name' => $object->getCustomerName(),
        ];
    }

    /**
     * @Route("/product/remove")
     * @param Request $request
     * @return JsonResponse
     */
    public function removeAction(Request $request)
    {
        $id = (int)$request->request->get('id');
        $em = $this->getDoctrine()->getManager();
        $product = $this->findProductOrResponseError($id);
        $product->setRemove(1);
        $em->flush();
        return $this->responseSuccess("Product remove success");
    }

    /**
     * @Route("/product/create")
     * @param Request $request
     * @return JsonResponse
     * @throws ConnectionException
     */
    public function createAction(Request $request)
    {
        /** @var EntityManager $em */
        $em = $this->getDoctrine()->getManager();
        # get material list from request
        $materials = $request->request->get('materials');
        if (!$materials) return $this->responseError(3001, 'No material choose');
        $_materials = [];
        $materialReposity = $em->getRepository(Material::class);
        foreach (explode(',', $materials) as $key => $material_id) {
            if ($material_id) {
                /** @var Material $material */
                $material = $materialReposity->find($material_id);
                if ($material) {
                    $_materials[] = $material;
                } else {
                    return $this->responseError(4003, "No Material found for id {$material_id}");
                }
            }
        }

        # TODO:to validate
        $name = $request->request->get('name');
        $customer_name = $request->request->get('customer_name');
        $description = $request->request->get('description');

        try {
            $product = (new ProductUtil($em))->create($name, $customer_name, $description, $_materials);
            return $this->responseSuccess('Product design success!', $this->fetchInfo($product));
        } catch (MaterialEmptyException $exception) {
            return $this->responseError($exception->getCode(), $exception->getMessage());
        }
    }


}